/**
 *
 */
package jp.seraph.same.model;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.NullArgumentException;

import jp.seraph.jsade.model.DefaultAngleVelocityCalculator;
import jp.seraph.jsade.model.JointIdentifier;
import jp.seraph.jsade.model.JointIdentifierContainer;
import jp.seraph.jsmf.codec.LinkMotionUtils;
import jp.seraph.jsmf.codec.PoseNameLinkMotionElement;
import jp.seraph.jsmf.codec.PoseNameLinkMotionElementData;
import jp.seraph.jsmf.motion.DefaultMotionSession;
import jp.seraph.jsmf.motion.EditableMotion;
import jp.seraph.jsmf.motion.EditableMotionManager;
import jp.seraph.jsmf.motion.Motion;
import jp.seraph.jsmf.motion.MotionManager;
import jp.seraph.jsmf.motion.MotionSession;
import jp.seraph.jspf.pose.PoseManager;

/**
 *
 *
 */
public class DefaultMotionModel implements MotionModel {
    public DefaultMotionModel(String aMotionName, EditableMotionManager aMotionManager, PoseManager aPoseManager, JointIdentifierContainer aIdContainer, PoseCollectionModel aPoseCollectionModel) {
        if(aMotionName == null)
            throw new NullArgumentException("aMotionName");
        if(aMotionManager == null)
            throw new NullArgumentException("aMotionManager");
        if(aPoseManager == null)
            throw new NullArgumentException("aPoseManager");
        if(aPoseCollectionModel == null)
            throw new NullArgumentException("aPoseCollectionModel");
        if(aIdContainer == null)
            throw new NullArgumentException("aIdContainer");

        mMotionName = aMotionName;
        mMotionManager = aMotionManager;
        mPoseManager = aPoseManager;
        mPoseCollectionModel = aPoseCollectionModel;
        mPoseNames = new ArrayList<String>();
        mIdContainer = aIdContainer;

        Motion tClone = aMotionManager.getMotion(aMotionName);
        for (MotionSession tSession : tClone) {
            PoseNameLinkMotionElement tElement = (PoseNameLinkMotionElement)tSession.toElementList().get(0);
            mPoseNames.add(tElement.getPoseName());
        }
    }

    private String mMotionName;
    private EditableMotionManager mMotionManager;
    private PoseManager mPoseManager;
    private PoseCollectionModel mPoseCollectionModel;
    private List<String> mPoseNames;
    private JointIdentifierContainer mIdContainer;

    /**
     *
     * @see jp.seraph.same.model.MotionModel#addPose(java.lang.String)
     */

    public void addPose(String aPoseName) {
        EditableMotion tMotion = mMotionManager.getEditableMotion(mMotionName);
        PoseNameLinkMotionElementData tData = new PoseNameLinkMotionElementData("Element", aPoseName, "", 0, new DefaultAngleVelocityCalculator(), mIdContainer.getIdentifiers().toArray(new JointIdentifier[0]));

        tMotion.addSession(new DefaultMotionSession("EditorSession", new PoseNameLinkMotionElement(mPoseManager, tData)));
        mPoseNames.add(aPoseName);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionModel#getPoseCount()
     */

    public int getPoseCount() {
        return mPoseNames.size();
    }

    /**
     *
     * @see jp.seraph.same.model.MotionModel#getPoseModel(int)
     */
    public PoseModel getPoseModel(int aIndex) {
        return this.getPoseModel(this.getPoseName(aIndex));
    }

    /**
     *
     * @see jp.seraph.same.model.MotionModel#getPoseModel(java.lang.String)
     */

    public PoseModel getPoseModel(String aPoseModelName) {
        return mPoseCollectionModel.getPose(aPoseModelName);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionModel#getPoseName(int)
     */

    public String getPoseName(int aIndex) {
        return mPoseNames.get(aIndex);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionModel#removePose(java.lang.String)
     */

    public boolean removePose(String aPoseName) {
        mPoseNames.remove(aPoseName);
        EditableMotion tMotion = mMotionManager.getEditableMotion(mMotionName);
        int tIndex = -1;

        Iterable<PoseNameLinkMotionElement> tElements = LinkMotionUtils.getMainElements(tMotion);
        for (PoseNameLinkMotionElement tElement : tElements) {
            tIndex++;
            if(tElement.getPoseName().equals(aPoseName)){
                tMotion.removeSession(tIndex);
                mMotionManager.setMotion(mMotionName, tMotion);
                return true;
            }
        }

        return false;

//        return mMotionManager.removePose(mMotionName, aPoseName);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionModel#toMotion()
     */

    public EditableMotion toMotion() {
        return mMotionManager.getEditableMotion(mMotionName);
    }
}
